extends layout

block headContent
	title Mining Summary

block content
	h1.h3 Mining Summary
	hr

	div.card.shadow-sm.mb-3
		div.card-body
			h3.h6.mb-0 Block Range
			hr

			div.clearfix
				div.float-left.mr-4
					div(id="time-range-buttons")
						h3.h6 Latest N Blocks
						div.btn-group
							a.btn.btn-primary.block-count-btn(href="javascript:void(0)", data-blockCount="144") 144
								small.ml-2 (~1d)
							a.btn.btn-outline-primary.block-count-btn(href="javascript:void(0)", data-blockCount="432") 432
								small.ml-2 (~3d)
							a.btn.btn-outline-primary.block-count-btn(href="javascript:void(0)", data-blockCount="1008") 1,008
								small.ml-2 (~7d)
							a.btn.btn-outline-primary.block-count-btn(href="javascript:void(0)", data-blockCount="4320") 4,320
								small.ml-2 (~30d)

				div.float-left.mr-4
					div(id="block-selections-buttons")
						h3.h6 Preconfigured

						div.dropdown
							button.btn.btn-outline-primary.dropdown-toggle(type="button", id="preconfigured-dropdown", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false") Selections
							div.dropdown-menu(aria-labelledby="preconfigured-dropdown")
								a.dropdown-item(href="javascript:void(0)", data-blocks="0-199") First 200 Blocks
								a.dropdown-item(href="javascript:void(0)", data-blocks="209900-210100") First Halving ±100
								a.dropdown-item(href="javascript:void(0)", data-blocks="419900-420100") Second Halving ±100
								a.dropdown-item(href="javascript:void(0)", data-blocks="629900-630100") Third Halving ±100
								a.dropdown-item(href="javascript:void(0)", data-blocks="481724-481924") SegWit Activation ±100

				div.float-left
					div(id="time-range-buttons")
						h3.h6 Custom Range

						form.form-inline.mr-3(id="custom-range-form")
							div.input-group
								input.form-control(type="text", id="custom-range-start", placeholder="min height", style="width: 125px;")
								input.form-control(type="text", id="custom-range-end", placeholder="max height", style="width: 125px;")
								div.input-group-append
									button.btn.btn-primary(type="submit") Go

	div#progress-wrapper.mb-huge
		div.card.shadow-sm.mb-3
			div.card-body
				h4.h6 Loading blocks: 
					span(id="block-progress-text")
				div.progress.mt-2(id="progress-bar", style="height: 7px;")
					div.progress-bar(id="data-progress", role="progressbar", aria-valuenow="0", aria-valuemin="0" ,aria-valuemax="100")
	

	div.card.shadow-sm.mb-3(id="summary-table", style="display: none;")
		div.card-body
			div.table-responsive
				table.table.table-striped.mb-0
					thead
						tr
							th.data-header Miner
							th.data-header.text-right Blocks
							th.data-header.text-right Transactions
							th.data-header.text-right Block Rewards
							th.data-header.text-right Fees Collected
							
					tbody(id="summary-table-body")
						tr(id="miner-summary-prototype", style="display: none;")
							td.data-cell.text-monospace.miner-name
							td.data-cell.text-monospace.text-right
								span.miner-block-count
								small.text-muted.miner-block-percent.ml-2
							td.data-cell.text-monospace.text-right
								span.miner-tx-count
								small.text-muted.miner-tx-percent.ml-2
							td.data-cell.text-monospace.text-right
								span.miner-subsidy
								small.text-muted.miner-subsidy-percent.ml-2
								//- var currencyValue = new Decimal(summary.totalSubsidiesCollected);
								//include ./includes/value-display.pug
							td.data-cell.text-monospace.text-right
								span.miner-fees
								small.text-muted.miner-fees-percent
								//- var currencyValue = new Decimal(summary.totalFeesCollected);
								//include ./includes/value-display.pug

						tr(id="miner-summary-totals", style="display: none;")
							th.data-cell.text-monospace.miner-name Total
							th.data-cell.text-monospace.text-right
								span.miner-block-count
								small.text-muted.miner-block-percent.ml-2 (100%)
							th.data-cell.text-monospace.text-right
								span.miner-tx-count
								small.text-muted.miner-tx-percent.ml-2 (100%)
							th.data-cell.text-monospace.text-right
								span.miner-subsidy
								//- var currencyValue = new Decimal(summary.totalSubsidiesCollected);
								//include ./includes/value-display.pug
							th.data-cell.text-monospace.text-right
								span.miner-fees
								//- var currencyValue = new Decimal(summary.totalFeesCollected);
								//include ./includes/value-display.pug

	if (false)
		pre
			code.json #{JSON.stringify(summariesByMiner, null, 4)}

block endOfBody
	script(src='./js/decimal.js')
	script.
		var currentBlockHeight = !{currentBlockHeight};
		$(document).ready(function() {
			$("#time-range-buttons .block-count-btn").on("click", function() {
				// highlight current selection
				$("#time-range-buttons .block-count-btn").removeClass("btn-primary").addClass("btn-outline-primary");
				$(this).addClass("btn-primary").removeClass("btn-outline-primary");
				$("#preconfigured-dropdown").removeClass("btn-primary").addClass("btn-outline-primary");
				
				var blockCount = parseInt($(this).attr("data-blockCount"));
				
				$(".miner-summary-row").remove();

				$("#data-progress").css("width", "0%");
				$("#block-progress-text").text("");

				$("#summary-table").hide();
				$("#progress-wrapper").show();

				getData(currentBlockHeight, blockCount, 15);
			});

			$("#block-selections-buttons .dropdown-item").on("click", function() {
				// highlight current selection
				$("#time-range-buttons .block-count-btn").removeClass("btn-primary").addClass("btn-outline-primary");
				$("#preconfigured-dropdown").removeClass("btn-outline-primary").addClass("btn-primary");
				
				var blocks = $(this).attr("data-blocks");
				var bStartEnd = blocks.split("-");
				var bStart = parseInt(bStartEnd[0]);
				var bEnd = parseInt(bStartEnd[1]);

				$(".miner-summary-row").remove();

				$("#data-progress").css("width", "0%");
				$("#block-progress-text").text("");

				$("#main-content").hide();
				$("#progress-wrapper").show();

				getData(bEnd, bEnd - bStart + 1, 15);
			});

			$("#custom-range-form").on("submit", function() {
				// highlight current selection
				$("#time-range-buttons .block-count-btn").removeClass("btn-primary").addClass("btn-outline-primary");
				$("#preconfigured-dropdown").removeClass("btn-primary").addClass("btn-outline-primary");
				
				var bStart = parseInt($("#custom-range-start").val());
				var bEnd = parseInt($("#custom-range-end").val());

				$(".miner-summary-row").remove();

				$("#data-progress").css("width", "0%");
				$("#block-progress-text").text("");

				$("#main-content").hide();
				$("#progress-wrapper").show();

				getData(bEnd, bEnd - bStart + 1, 15);

				return false;
			});

			getData(currentBlockHeight, 144, 15);
		});

		function getData(blockStart, count, chunkSize) {
			$("#time-range-buttons .block-count-btn").addClass("disabled");
			$("#block-selections-buttons .dropdown-item").addClass("disabled");

			var chunks = [];
			var blockIndex = blockStart;
			while (blockIndex > blockStart - count) {
				var chunk = [];
				for (var i = blockIndex; (i > (blockIndex - chunkSize) && i > (blockStart - count)); i--) {
					chunk.push(i);
				}

				blockIndex -= chunkSize;
				chunks.push(chunk);
			}

			//console.log(JSON.stringify(chunks));
			//alert(JSON.stringify(chunks));

			var results = [];

			var statusCallback = function(chunkIndexDone, chunkCount) {
				//console.log("Done: " + Math.min(((chunkIndexDone + 1) * chunkSize), count) + " of " + count);

				var wPercent = `${parseInt(100 * (chunkIndexDone + 1) / parseFloat(chunkCount))}%`;
				
				$("#data-progress").css("width", wPercent);
				$("#block-progress-text").text(`${Math.min(((chunkIndexDone + 1) * chunkSize), count).toLocaleString()} of ${count.toLocaleString()} (${wPercent})`);
			};

			var finishedCallback = function() {
				$("#time-range-buttons .block-count-btn").removeClass("disabled");
				$("#block-selections-buttons .dropdown-item").removeClass("disabled");

				//console.log(JSON.stringify(results));

				var summary = summarizeBlockData(results);


				for (var i = 0; i < summary.minerNamesSortedByBlockCount.length; i++) {
					var minerName = summary.minerNamesSortedByBlockCount[i];
					var minerSummary = summary.summariesByMiner[minerName];

					var row = $("#miner-summary-prototype").clone();
					row.attr("id", null);
					row.addClass("miner-summary-row");

					var blockHeightsHtml = "";
					for (var j = 0; j < minerSummary.blockHeights.length; j++) {
						blockHeightsHtml += `<li><a href='./block-height/${minerSummary.blockHeights[j]}'>${minerSummary.blockHeights[j]}</a></li>`;
					}
					blockHeightsHtml = `<ol>${blockHeightsHtml}</ol>`
					
					row.find(".miner-name").text(minerName);

					row.find(".miner-block-count").html(`<a href='javascript:void(0);' onclick="javascipt:$('#miner-block-heights-${i}').toggle();" title="Click to show ${minerSummary.blockCount.toLocaleString()} block height(s)" data-toggle="tooltip">${minerSummary.blockCount.toLocaleString()}</a><br/><small id='miner-block-heights-${i}' style='display: none;'>${blockHeightsHtml}</small>`);
					row.find(".miner-block-percent").text(`(${new Decimal(minerSummary.blockCount).dividedBy(summary.overallSummary.blockCount).times(100).toDecimalPlaces(1)}%)`);
					
					row.find(".miner-tx-count").text(minerSummary.transactionCount.toLocaleString());
					row.find(".miner-tx-percent").text(`(${new Decimal(minerSummary.transactionCount).dividedBy(summary.overallSummary.transactionCount).times(100).toDecimalPlaces(1)}%)`);

					row.find(".miner-subsidy").text(minerSummary.totalSubsidiesCollected.toLocaleString());
					row.find(".miner-subsidy-percent").text(`(${new Decimal(minerSummary.totalSubsidiesCollected).dividedBy(summary.overallSummary.totalSubsidiesCollected).times(100).toDecimalPlaces(1)}%)`);

					row.find(".miner-fees").text(minerSummary.totalFeesCollected.toLocaleString());

					if (summary.overallSummary.totalFeesCollected > 0) {
						row.find(".miner-fees-percent").text(` (${new Decimal(minerSummary.totalFeesCollected).dividedBy(summary.overallSummary.totalFeesCollected).times(100).toDecimalPlaces(1)}%)`);
					}


					updateCurrencyValue(row.find(".miner-subsidy"), minerSummary.totalSubsidiesCollected);
					updateCurrencyValue(row.find(".miner-fees"), minerSummary.totalFeesCollected);
					

					row.show();

					$("#summary-table-body").append(row);
				}


				var totalsRow = $("#miner-summary-totals");
				totalsRow.find(".miner-block-count").text(summary.overallSummary.blockCount.toLocaleString());
				totalsRow.find(".miner-tx-count").text(summary.overallSummary.transactionCount.toLocaleString());
				totalsRow.find(".miner-subsidy").text(summary.overallSummary.totalSubsidiesCollected.toLocaleString());
				totalsRow.find(".miner-fees").text(summary.overallSummary.totalFeesCollected.toLocaleString());

				var parent = totalsRow.parent();
				parent.remove(totalsRow);
				parent.append(totalsRow);

				totalsRow.show();

				$("#summary-table").show();
				$("#progress-wrapper").hide();
			};

			getBlockData(results, chunks, 0, statusCallback, finishedCallback);
		}

		function getBlockData(results, chunks, chunkIndex, statusCallback, finishedCallback) {
			if (chunkIndex > chunks.length - 1) {
				finishedCallback();

				return;
			}

			var url = `./api/blocks-by-height/${chunks[chunkIndex]}`;
			
			//console.log(url);

			$.ajax({
				url: url

			}).done(function(result) {
				for (var i = 0; i < result.length; i++) {
					results.push(result[i]);
				}

				statusCallback(chunkIndex, chunks.length);
				
				getBlockData(results, chunks, chunkIndex + 1, statusCallback, finishedCallback);
			});
		}

		function summarizeBlockData(blocks) {
			var summariesByMiner = {};
			var minerNamesSortedByBlockCount = [];
			
			var overallSummary = {};
			overallSummary.blockCount = 0;
			overallSummary.transactionCount = 0;
			overallSummary.totalSubsidiesCollected = new Decimal(0);
			overallSummary.totalFeesCollected = new Decimal(0);
			overallSummary.blockSizeTotal = 0;

			for (var i = 0; i < blocks.length; i++) {
				var block = blocks[i];

				var miner = block.miner;
				if (!miner) {
					miner = {name:"Unknown"};
				}

				if (!summariesByMiner[miner.name]) {
					minerNamesSortedByBlockCount.push(miner.name);

					summariesByMiner[miner.name] = {};
					summariesByMiner[miner.name].miner = miner;

					summariesByMiner[miner.name].blockCount = 0;
					summariesByMiner[miner.name].transactionCount = 0;
					summariesByMiner[miner.name].totalSubsidiesCollected = new Decimal(0);
					summariesByMiner[miner.name].totalFeesCollected = new Decimal(0);
					summariesByMiner[miner.name].blockSizeTotal = 0;

					summariesByMiner[miner.name].blockHeights = [];


					if (blocks[0].weight) {
						summariesByMiner[miner.name].blockWeightTotal = 0;
					}
				}

				summariesByMiner[miner.name].blockCount++;
				summariesByMiner[miner.name].transactionCount += block.tx.length;
				summariesByMiner[miner.name].totalSubsidiesCollected = summariesByMiner[miner.name].totalSubsidiesCollected.add(new Decimal(block.subsidy));
				summariesByMiner[miner.name].totalFeesCollected = summariesByMiner[miner.name].totalFeesCollected.add(new Decimal(block.totalFees));
				summariesByMiner[miner.name].blockSizeTotal += block.size;

				summariesByMiner[miner.name].blockHeights.push(block.height);

				if (blocks[0].weight) {
					summariesByMiner[miner.name].blockWeightTotal += block.weight;
				}


				overallSummary.blockCount++;
				overallSummary.transactionCount += block.tx.length;
				overallSummary.totalSubsidiesCollected = overallSummary.totalSubsidiesCollected.add(new Decimal(block.subsidy));
				overallSummary.totalFeesCollected = overallSummary.totalFeesCollected.add(new Decimal(block.totalFees));
				overallSummary.blockSizeTotal += block.size;

				if (blocks[0].weight) {
					overallSummary.blockWeightTotal += block.weight;
				}
			}

			minerNamesSortedByBlockCount.sort(function(a, b) {
				return ((summariesByMiner[a].blockCount > summariesByMiner[b].blockCount) ? -1 : 1);
			});

			return {summariesByMiner:summariesByMiner, minerNamesSortedByBlockCount:minerNamesSortedByBlockCount, overallSummary:overallSummary};
		}
